home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-03 / dosbasic.zip / ASM.ZIP / FILES.ASM < prev    next >
Assembly Source File  |  1990-12-19  |  24KB  |  664 lines

  1. ;«RM82»«TS8,16,24,32,40,48»
  2. ;updated 11/21/90
  3.  
  4. ;============================================================================
  5. ;   Copyright (C) Copr. 1990 by Sidney J. Kelly
  6. ;           All Rights Reserved.
  7. ;           Sidney J. Kelly
  8. ;           150 Woodhaven Drive
  9. ;           Pittsburgh, PA 15228
  10. ;           home phone 412-561-0950 (7pm to 9:30pm EST)
  11. ;============================================================================
  12.  
  13. DOSSEG
  14. .MODEL MEDIUM
  15.  
  16. Public GETDRIVE, GETSUB, DRVSPACE, SETDRIVE, SUBEXIST, FLOPPYREADY, FLOPPYDRIVES, HARDRIVES, GETCURRENTNAME, TRUENAME, GETFULLPATH
  17.  
  18. .CODE
  19.  
  20. ; Please do not remove
  21. Copyright       DB    13,10,'Copyright Copr. (C) 1990 Sidney J. Kelly',13,10
  22. Copyright1      DB    'All Rights Reserved',13,10,26
  23.  
  24. ;============================================================================
  25. ; DECLARE SUB GETDRIVE(DRIVE$)
  26. ; CALL GETDRIVE(DRIVE$)
  27. ; Returns current drive name
  28. ; If LEN(DRIVE$)=0 then nothing happens
  29. ;
  30. ; Assumes that DRIVE$ is a near string, not TYPEd or part of a far string
  31. ; array.  In other words, assumes DRIVE$ is in DGROUP
  32. ;============================================================================
  33.  
  34. EVEN
  35. GETDRIVE        PROC           FAR
  36.         Push           BP
  37.         Mov            BP,SP        ;save base frame
  38.         Mov            BX,[BP+6]
  39.         Mov            CX,[BX]
  40.         Jcxz           Error1       ;test LEN(Drive$) if 0 exit
  41.         Mov            AH,19h
  42.         Int            21h
  43.         Add            AL,'A'       ;Add A to value
  44.         Xor            AH,AH        ;clear AH to 0
  45.         Mov            BX,[BP+6]    ;get address of string descripter
  46.         Mov            BX,[BX+2]    ;get actual string address
  47.         Mov            [BX],AL      ;store AL in Drive$
  48. Error1:
  49.         Pop            BP
  50.         Ret            2            ; one parameter passed
  51.                         ; so remove it
  52. GETDRIVE        ENDP
  53.  
  54. ;============================================================================
  55. ; DECLARE SUB GETSUB (PATH AS STRING * 64, PATHLEN%)
  56. ; Returns current subdirectory path, without Drive:\, (i.e. no "A:\")
  57. ; if LEN(Path$) not = to 64 then returns a pathlen% of -1
  58. ;
  59. ; PATH$ can not be a TYPEd string or a variable in a string array
  60. ; because there is a chance that string will be outside DGROUP.
  61. ; This routine assumes that Path$ is a near string.
  62. ;============================================================================
  63.  
  64. EVEN
  65. GETSUB  PROC  FAR
  66.         Push      BP           ;set up base pointer
  67.         Mov       BP,SP        ;allow us to address the stack
  68.         Push      SI           ;save index registers
  69.         Push      DI           ; ditto
  70.         Mov       AX,SS
  71.         Mov       ES,AX        ;set ES = to DGROUP for scasb
  72.  
  73.         assume    ES:@data
  74.  
  75.         Mov       BX,[BP+8]    ;get address of Path$
  76.         Mov       AX,ES:[BX]
  77.         Cmp       AX,64        ;if LEN(PATH$) <> 64
  78.         JNE       Error        ;then Error
  79.         Mov       SI,ES:[BX+2] ;it has to be 64 so Pathlen% value is
  80.         Mov       DI,SI        ;calculated correctly below
  81.         Xor       DL,DL        ;select default drive
  82.         Mov       AH,47h       ;get current directory
  83.         Int       21h
  84.         JC        Error        ;if carry set, directory invalid
  85.         Mov       CX,64        ;determine length of Path$
  86.         Xor       AL,AL        ;clear AL, the value to search
  87.                        ;for ending null
  88.         Cld                    ;clear direction flag
  89.         Repnz     Scasb        ;scan until reach end of Path$
  90.         Mov       AX,63        ;determine length of Path$
  91.         Sub       AX,CX
  92.         Jmp       Short finis
  93. Error:
  94.         Mov       AX,-1        ;return Pathlen% = -1 if error
  95. finis:
  96.         Mov       BX,[BP+6]
  97.         Mov       ES:[BX],AX
  98.         Pop       DI           ;restore registers used
  99.         Pop       SI
  100.         Pop       BP
  101.         Ret       4
  102. GETSUB        ENDP
  103.  
  104. ;============================================================================
  105. ; DECLARE SUB DRVSPACE (DRIVE$,SPACE&)
  106. ; checks if DRIVE$ <"A" or >"z", or if >"Z" & less <"a"
  107. ; Drive of "@" gives the current drive
  108. ; Invalid DRIVE$ gives a free space of 0
  109. ; Note: DOS does not correctly adjust this if use JOIN or SUBST and
  110. ; try to determine the size of a non-default drive.
  111. ;============================================================================
  112.  
  113. EVEN
  114. DRVSPACE  PROC  FAR
  115.         Push    BP
  116.         Mov     BP,SP
  117.         Mov     BX,[BP+8]       ;get drive letter from first parameter
  118.         Mov     CX,[BX]
  119.         Jcxz    Error_Set       ;DRIVE$ is a null string so exit
  120.         Mov     BX,[BX+2]       ;get string address
  121.         Mov     DL,[BX]         ;store string in DL
  122.         Xor     DH,DH
  123.         Cmp     DL,'@'          ;check if less than "@"
  124.         JB      Error_Set
  125.         Cmp     DL,'z'          ;check if > "z"
  126.         JA      Error_Set
  127.         Cmp     DL,'@'          ;select current if "@"
  128.         JNE     Spec_drive      ;check if want current drive
  129.         Mov     AH,36h
  130.         Xor     DX,DX           ;0 is current drive number
  131.         Int     21h             ;read current drive free space
  132.         Cmp     AX,0ffffh       ;did an error occur?
  133.         JE      Error_Set       ;routine returned invalid drive
  134.         Jmp     Short Quit      ;valid drive
  135. Spec_drive:
  136.         And     DL,1fh          ;allow A to Z or a to z
  137.         Dec     DL
  138.         Cmp     DX,19h          ;final range check if > "Z" and < "a"
  139.         JA      Error_Set       ;greater than "Z" so quit
  140.         Inc     DL
  141.         Mov     AH,36h
  142.         Int     21h
  143.         Cmp     AX,0ffffh       ;did an error occur?
  144.         JE      Error_Set
  145. Quit:                                   ;store free SPACE& in DX:AX pair
  146.         Mul     CX              ;multiply sectors/cluster * bytes per sector
  147.         Mul     BX              ;multiply product by no. free clusters
  148.         Jmp     Short Finis1    ;the order of math is important
  149. Error_Set:
  150.         Xor     AX,AX           ;returns a free SPACE& of 0
  151.         Mov     DX,AX           ;saves a clock on 8086 chips
  152. Finis1:
  153.         Mov     BX,[BP+6]       ;Stores the SPACE& in 2d parameter
  154.         Mov     [BX],AX         ;store lowbyte from AX
  155.         Mov     [BX+2],DX       ;store hibyte from DX
  156.         Pop     BP
  157.         Ret     4
  158. DRVSPACE   ENDP
  159.  
  160. ;============================================================================
  161. ; DECLARE SUB SETDRIVE (DRIVE$,ErrCode%)
  162. ; no change occurs if DRIVE$ <"A" or >"z", or if >"Z" & less <"a"
  163. ; Returns   ErrCode% =  0 (False) if no errors
  164. ;                    = -1 (True)  if errors
  165. ; error checking includes range check and real test if a change occured
  166. ;============================================================================
  167.  
  168. EVEN
  169. SETDRIVE PROC FAR
  170.         Push    BP
  171.         Mov     BP,SP       ;set base frame pointer
  172.         Mov     AH,19h      ;get default drive
  173.         Int     21h
  174.         Xor     CH,CH
  175.         Mov     CL,AL       ;store in CL
  176.         Mov     BX,[BP+8]   ;get drive letter from first parameter
  177.         Mov     BX,[BX+2]   ;get string address
  178.         Mov     DL,[BX]     ;store string in DL
  179.         Xor     DH,DH
  180.         Cmp     DL,'A'      ;check if less than "A"
  181.         JB      Error_Set1
  182.         Cmp     DL,'z'      ;check if > "z"
  183.         JA      Error_Set1
  184.         And     DL,1fh      ;allow A to Z or a to z
  185.         Dec     DL          ;subtract one to make DX zero based drive number
  186.         Cmp     DL,19h      ;final range check if > "Z" and < "a"
  187.         JA      Error_Set1  ;greater than "Z" so quit
  188.         Cmp     CL,DL
  189.         je      Quiter      ;current equal's new drive so don't bother
  190.         Mov     AH,0Eh      ;change drive
  191.         Int     21h
  192.         Mov     AX,1900h    ;get current directory again to
  193.                     ;see if change worked
  194.         Int     21h
  195.         Cmp     AL,DL       ;DL holds user selected drive
  196.         JNE     Error_Set1  ;unable to make a change so set error
  197. Quiter:
  198.         Xor     AX,AX       ;clears ERRORCODE% to 0
  199.         Jmp     Short Finis2
  200. Error_Set1:
  201.         Mov     AX,-1       ;Sets ERRORCODE% to -1 if error occured
  202. Finis2:
  203.         Mov     BX,[BP+6]   ;Stores the ERRORCODE% in 2d parameter
  204.         Mov     [BX],AX
  205.         Pop     BP
  206.         Ret     4
  207. SETDRIVE   ENDP
  208.  
  209. ;============================================================================
  210. ; DECLARE SUB SUBEXIST (PATH$+CHR$(0),ErrCode%)
  211. ; Returns ErrCode%  =  0  (False) if no errors,
  212. ;                   = -1  (True)  if errors
  213. ; If a drive change is required, subdirectory on other drive will be made
  214. ; the "current" subdirectory on that other drive.
  215. ;
  216. ; PATH$ cannot be a TYPEd string or a variable in a string array
  217. ; because there is a chance that string will be outside DGROUP.  String
  218. ; cocentenation is used to make sure it is in DGROUP.
  219. ;============================================================================
  220.  
  221. EVEN
  222. StoragePath  db   0,':\', 64 dup (0)         ;temporarily store information.
  223.                          ;By storing DATA in code seg,
  224.                          ;this routine cannot be used
  225.                          ;under OS/2.  We do it
  226.                          ;to save space in DGROUP
  227. EVEN
  228. SUBEXIST  PROC FAR
  229.         Push      BP
  230.         Mov       BP,SP
  231.         Push      DS
  232.         Push      SI
  233.         Push      DI
  234.         Mov       AH,19h          ;get original drive
  235.         Int       21h
  236.         Mov       StoragePath,AL  ;store drive number for later use
  237.         Push      DS              ;save DS
  238.         Mov       AX,CS           ;faster than PUSH CS, POP DS on 8088
  239.         Mov       DS,AX           ;set DS == CS
  240.         Mov       AH,47h          ;get original subdirectory
  241.         Xor       DL,DL           ;of current drive
  242.  
  243.         ASSUME    DS:@code        ;tell DOS of change
  244.  
  245.         Mov       SI, offset StoragePath+3    ;give original path
  246.         Mov       DI, SI
  247.         Int       21h
  248.         Pop       DS
  249.  
  250.         ASSUME    DS:@data
  251.  
  252.         Mov       BX,[BP+8]       ;get Path$
  253.         Mov       DI,[BX+2]       ;store address of Path$ in DI
  254.         Mov       CX,[BX]         ;get length of string in CX
  255.         Jcxz      String_Too_Short;if Path$ too short, bail out
  256.         Cmp       CX,03           ;check string size
  257.         JB        Short_Path      ;if LEN(Path$) < 3,
  258.                       ;don't check for drive
  259.         Cmp   byte PTR [DI+1],':' ;check for colon
  260.         JNE       Short_Path      ;skip drive check if no colon
  261.         Mov       DL,[DI]         ;drive letter to DL
  262.         And       DX,001fh        ;capitalize letter
  263.         Dec       DX              ;reduce by zero, for zero bias
  264.         Mov       AH,0Eh          ;select drive
  265.         Int       21h
  266.         Inc       DI              ;move pointer past DRIVE
  267.         Inc       DI              ;move pointer past colon
  268. Short_Path:
  269.         Mov       DX,DI           ;move pointer to DX
  270.         Mov       AH,3Bh          ;change to new "current" directory
  271.         Mov       SI,-1           ;assume error
  272.         Int       21h
  273.         JC        SubEx_Err       ;error if carry set
  274.         Xor       SI,SI           ;no error so return 0
  275. SubEx_Err:
  276.         Mov       BX,[BP+6]
  277.         Mov       [BX],SI         ;store result from SI in ErrCode%
  278.         Mov       DL, StoragePath ;using original default drive
  279.         Mov       AH,0Eh          ;select original drive
  280.         Int       21h
  281.         Add       DL,65           ;convert drive letter to ASCII character
  282.         Mov       StoragePath,DL  ;give us original drive letter
  283.  
  284.         Mov       AX,CS           ;set DS == CS
  285.         Mov       DS,AX
  286.  
  287.         Mov       AH,3Bh          ;change back to original subdirectory
  288.  
  289.         ASSUME    DS:@code, ES:NOTHING
  290.  
  291.         Mov       DX, offset StoragePath
  292.         Int       21h
  293. SubEx_Finis:
  294.         Pop       DI              ; restore saved registers
  295.         Pop       SI
  296.         Pop       DS
  297.  
  298.         ASSUME    DS:@data
  299.  
  300.         Pop       BP
  301.         Ret       4               ; remove 2 * 2 parameters
  302.  
  303. String_Too_Short:
  304.         Mov       SI,-1           ;Path$ a "" string, why bother
  305.         Mov       BX,[BP+6]       ;report ErrCode of TRUE
  306.         Mov       [BX],SI         ;store result from SI in ErrCode%
  307.         Jmp       Short SubEx_Finis
  308. SUBEXIST        ENDP
  309.  
  310. ;============================================================================
  311. ; DECLARE SUB FLOPPYREADY (DRIVE$, ErrCode%)
  312. ; Tests if floppy drive is ready, on a one floppy system
  313. ; treats drive B: as equivalent to drive A:
  314. ; ErrCode
  315. ;        128 = Time Out Error
  316. ;         80 = Track error
  317. ;        -1  = Drive$ is not valid
  318. ;         0  = All a.o.k.
  319. ; Note : A critical error routine is not necessary for this routine to work
  320. ;============================================================================
  321.  
  322. EVEN
  323. FLOPPYREADY   PROC    FAR
  324.         Push            BP
  325.         Mov             BP,SP
  326.         Push            SI
  327.         call            _Floppy        ;get actual # of floppies in AX
  328.         Mov             SI,0003        ;assume 3 drives
  329.         Mov             BX,[BP+8]
  330.         Mov             CX,[BX]        ;test LEN(DRIVE$)
  331.         Jcxz            ErrorFound     ;if zero, then quit
  332.         Mov             BX,[BX+2]      ; get actual string
  333.         Mov             DL,[BX]        ;store in DL
  334.         And             DL,1Fh         ;capitalize it
  335.         Cmp             DL,2
  336.         JNE             @f             ;Check if want drive B: on
  337.         Cmp             AL,1           ;a one floppy system
  338.         JNE             @f
  339.         Dec             DL             ;make call for B:, mimic A:
  340. @@:
  341.         Cmp             DL,AL          ;if greater than allowed floppy #
  342.         JA              ErrorFound
  343.         Dec             DL             ;zero bias
  344. Redo:
  345.         Mov             AX,401h
  346.         Mov             CX,1
  347.         Xor             DH,DH          ;verify 1 sector of disk
  348.         Int             13h
  349.         Or              AH,AH          ;check for errors
  350.         Mov             AX,0000        ;can't use XOR because
  351.                            ;wd change flags
  352.         JZ              NormalExit     ;found none so exit
  353.         Dec             SI             ;decriment no. of drives
  354.         JZ              @f             ;jump if no more drives
  355.         Xor             AH,AH          ;reset drive if error
  356.         Int             13h            ;try again
  357.         Jmp             Short Redo
  358. @@:
  359.         Mov             AX,0100h       ;read reset status
  360.         Int             13h
  361.         Xchg            AH,AL          ;put return value in AL
  362.         Xor             AH,AH          ;clear AH
  363. NormalExit:
  364.         Mov             BX,[BP+6]
  365.         Mov             [BX],AX        ;store in ErrCode
  366.         Pop             SI             ;restore saved registers
  367.         Pop             BP
  368.         Ret             4              ;remove 2 * 2 parameters
  369. ErrorFound:
  370.         Mov             AX,-1          ;return -1 for error
  371.         Jmp             NormalExit
  372. FLOPPYREADY ENDP
  373.  
  374. ;---------------------------------------------------------------------
  375. ; DECLARE SUB FLOPPYDRIVES(NoDrives%)
  376. ; Returns number of physical floppy drives in system
  377. ;---------------------------------------------------------------------
  378.  
  379. EVEN
  380. FLOPPYDRIVES    PROC   FAR
  381.         Push            BP
  382.         Mov             BP,SP
  383.         Call            _Floppy
  384.         Mov             BX,[BP+6]
  385.         Mov             [BX],AX       ;store AX in value
  386.         Pop             BP
  387.         Ret             2
  388. FLOPPYDRIVES        ENDP
  389.  
  390. EVEN
  391. _Floppy   Proc  Near
  392.         Int            11h
  393.         Shr            AX,1          ;test if have any floppies
  394.         JB             @f            ;jump if carry flag set
  395.         Xor            AX,AX         ;else clear AX
  396.         Jmp            Short Fins1   ;quit
  397.  @@:
  398.         And            AX,60h        ;mask off floppy bits
  399.         Mov            CL,05         ;count the number of floppies
  400.         Shr            AX,CL
  401.         Inc            AX            ;increment the final count
  402. Fins1:
  403.         Ret
  404. _Floppy   ENDP
  405.  
  406. ;---------------------------------------------------------------------
  407. ; DECLARE SUB HARDDRIVES(NoDrives%)
  408. ; Returns number of physical hard disks in system
  409. ;---------------------------------------------------------------------
  410.  
  411. EVEN
  412. HARDRIVES    PROC   FAR
  413.         Push            BP
  414.         Mov             BP,SP
  415.         Xor             AX,AX
  416.         Mov             ES,AX
  417.         Mov             BX,ES:[0475h] ; get info from 0040:0075h
  418.         Mov             AX,BX
  419.         And             AX,3          ; keep within range 0-4
  420.         Mov             BX,[BP+6]
  421.         Mov             [BX],AX       ; store AX in value
  422.         Pop             BP
  423.         Ret             2
  424. HARDRIVES ENDP
  425.  
  426. ;=========================================================================
  427. ; DECLARE SUB GETCURRENTNAME (FName as STRING * 64, FileLength%)
  428. ; Returns current filename for dos version 3.xx and above
  429. ; if LEN(FName$) <> 64 then returns a FileLength% of -1
  430. ;
  431. ; FName$ can not be a TYPEd string or a variable in a string array
  432. ; because there is a chance that string will be outside DGROUP.
  433. ; This routine assumes that FName$ is a near string.
  434. ; Function returns an error if DOS version < 3.xx since function is not
  435. ; supported for that version.
  436. ;=========================================================================
  437.  
  438. EVEN
  439. Env_Seg      dw      0
  440. Env_Len      dw      0
  441.  
  442. EVEN
  443. GETCURRENTNAME  PROC  FAR
  444.         Push            BP           ; set up base pointer
  445.         Mov             BP,SP        ; allow us to address the stack
  446.         Push            SI           ; save index registers
  447.         Push            DI           ; ditto
  448.         Push            DS           ; save segment registers
  449.         Mov             AH,30h       ; check if DOS version > 2.xx
  450.         Int             21h
  451.         Cmp             AL,3
  452.         JB              Error12      ; error if less than 3.00
  453.         Cld                          ; clear direction flag
  454.         Mov             AH,62h       ; get PSP address
  455.         Int             21h
  456.         Mov             ES,BX        ; store PSP address in ES
  457.         Mov             ES,ES:[002ch]; store PSP environment segment
  458.                          ; address in ES
  459.         Mov             Env_Seg,ES   ; save environment address
  460.         Xor             DI,DI        ; clear DI
  461.         Xor             AL,AL        ; clear AL
  462.         Mov             CX,8000h     ; assume environment segment
  463.                          ; is 32kb max
  464. DoubleNullLoop:
  465.         Repne           Scasb        ; search using ES:DI
  466.                          ; until find a null
  467.                          ; (can't use scasw because the
  468.                          ; double null may fall on odd
  469.                          ; address)
  470.  
  471.         Scasb                        ; find the second null
  472.         Jne     DoubleNullLoop
  473.  
  474.         Add             DI,2         ; skip over markers
  475.                          ; db 0, 1
  476.         Mov             Env_Len,DI   ; save end of environment
  477.                          ;   address
  478.  
  479.         Mov             AX,SS
  480.         Mov             ES,AX        ; set ES = to DGROUP for scasb
  481.  
  482.         Assume  ES:@data
  483.  
  484.         Mov             BX,[BP+8]    ; get address of Path$
  485.         Mov             AX,ES:[BX]
  486.         Cmp             AX,64        ; if LEN(PATH$) <> 64
  487.         Jne             Error12      ; then Error
  488.  
  489.         Mov             SI,ES:[BX+2] ; it has to be 64 so FileLength%
  490.                          ; value is calculated correctly below
  491.         Mov             DI,SI        ; copy SI:offset in DI for use by
  492.                          ; Movsb and Scasb below.
  493.  
  494.         Push            DI
  495.         Mov             CX,64        ; copy Name into FName$
  496.         Mov             DS,Env_Seg
  497.         Mov             SI,Env_Len
  498.         Rep             Movsb        ; copy DS:SI to ES:DI
  499.  
  500.         Mov             CX,64        ; length of FName$
  501.         Xor             AL,AL        ; clear AL, the search value
  502.         Pop             DI           ; search for null at end of name
  503.         Repnz           Scasb        ; uses ES:DI to search
  504.                          ; scan until reach end of FName$
  505.         Mov             AX,63        ; determine length of FName$
  506.         Sub             AX,CX        ; before the null
  507.         Jmp             Short Finis12
  508. Error12:
  509.         Mov             AX,-1        ; return FileLength% = -1
  510.                          ; if error
  511. Finis12:
  512.         Mov             BX,[BP+6]
  513.         Mov             ES:[BX],AX
  514.         Pop             DS           ; restore registers used
  515.         Pop             DI
  516.         Pop             SI
  517.         Pop             BP
  518.         Ret             4            ; remove 2 * 2 parameters
  519. GETCURRENTNAME      ENDP
  520.  
  521. ;============================================================================
  522. ; DECLARE SUB TRUENAME (OrigFile$+CHR$(0), TrueFName$, FileLength%)
  523. ; Purpose:
  524. ;     Allows user to test for SUBST, ASSIGN, and JOIN using an
  525. ;     undocumented call for DOS Version 3.xx and above
  526. ;     The returned name will contain technically correct Drive: and Path
  527. ;     information.  However, the OrigFile$ is not checked so ? and * may be
  528. ;     used, the OrigFile$ may even be non-existant.
  529. ;
  530. ; Shortcuts:
  531. ; OrigFile$ = "." to obtain current drive & subdirectory name
  532. ; OrigFile$ = ".." to obtain immediate parent drive & subdirectory name
  533. ;
  534. ; Usage:
  535. ;     TrueFName$ = STR$(67,0)
  536. ;     CALL TRUENAME(OrigFile$ + CHR$(0), TrueFName$, FileLength%)
  537. ;     IF FileLength% = -1 THEN
  538. ;            Error
  539. ;     ELSE
  540. ;          TrueFName$=LEFT$(TrueFName$, FileLength%)
  541. ;     END IF
  542. ;============================================================================
  543.  
  544. EVEN
  545. TRUENAME PROC FAR
  546.         Push    BP
  547.         Mov    BP,SP        ; make stack addressable
  548.         Push    DI              ; save variables we use
  549.         Push    SI
  550.  
  551.         Mov     AH,30h        ; check if DOS version > 2.xx
  552.         Int     21h
  553.         Cmp     AL,3            ; AL contains the major version
  554.         JB      Error15         ; If less than 3.00, Error15
  555.         Mov    BX,[BP+8]       ; get TrueFName$
  556.         Mov    CX,[BX]         ; get length of string
  557.         JCXZ    Error14         ; if zero, Error
  558.         Cmp    CX,67           ; if not equal to 67 bytes, Error
  559.         JNE    Error14
  560.         Mov     DI,[BX+2]       ; get address of TrueFName$ string
  561.         Mov    BX,[BP+10]      ; get length of OrigFile$
  562.         Mov    CX,[BX]         ; if length is zero, then Error
  563.         JCXZ    Error14
  564.         Mov    SI,[BX+2]    ; get address of OrigFile$
  565.  
  566.         Mov    AX,DS           ; faster than PUSH & POP on 8088
  567.         Mov     ES,AX           ; make ES==DS
  568.         Push    DI        ; save address of DI
  569.  
  570.         ; input string DS:SI, output ES:DI
  571.         Mov    AH,60h          ; call undocumented Expand Path Name
  572.                 Int    21h             ; Dettmann, DOS Programmer's Reference
  573.                     ; 2d Edition (Que 1989), page 660
  574.                     ; Very good book
  575.  
  576.         Pop    DI        ; reset DI
  577.         JC      Error14         ; bad character in OrigFile$
  578.  
  579.         Mov    CX,67           ; length of TrueFName$
  580.         Xor    AL,AL           ; clear AL, the search value
  581.         Cld            ; clear the direction flag
  582.                 Repnz   Scasb           ; uses ES:DI to search
  583.                     ; scan until reach end of TrueFName$
  584.         Mov    AX,66           ; determine length of TrueFName$
  585.         Sub     AX,CX           ; before the null
  586.         Jmp     Short Quit14    ; end routine
  587. Error14:
  588.         Mov    AX,-1           ; return a -1 for FileLength%
  589. Quit14:
  590.         Mov    BX,[BP+6]
  591.                 Mov    [BX],AX      ; store AX in FileLength%
  592.                 Pop    SI        ; restore saved registers
  593.         Pop    DI
  594.         Pop    BP
  595.         Ret    6               ; clear variables off stack
  596.  
  597. Error15:                ; report DOS version is <3.xx
  598.         Xor    AX,AX           ; so no danger of SUBST, JOIN
  599.         Jmp    Short Quit14    ; or ASSIGN
  600. TRUENAME ENDP
  601.  
  602. ;=========================================================================
  603. ; DECLARE SUB GETFULLPATH (PATH$, PATHLEN%)
  604. ; Returns current subdirectory path, with Drive:\, e.g. "A:\"
  605. ; if LEN(Path$) <>  67 then returns a pathlen% of -1
  606. ;
  607. ; PATH$ can not be a TYPEd string or a variable in a string array
  608. ; because there is a chance that string will be outside DGROUP.
  609. ; This routine assumes that Path$ is a near string.
  610. ;=========================================================================
  611.  
  612. EVEN
  613. GETFULLPATH  PROC  FAR
  614.         Push      BP           ;set up base pointer
  615.         Mov       BP,SP        ;allow us to address the stack
  616.         Push      SI           ;save index registers
  617.         Push      DI           ; ditto
  618.  
  619.         Mov       BX,[BP+8]    ;get address of Path$
  620.         Mov       AX,[BX]
  621.         Cmp       AX,67        ;if LEN(PATH$) <> 67
  622.         JNE       Error2       ;then Error
  623.  
  624.         Mov       AX,SS
  625.         Mov       ES,AX        ;set ES == to DGROUP for scasb
  626.  
  627.         assume  ES:@data
  628.  
  629.         Mov       AH,19h       ;get current drive
  630.         Int       21h
  631.         Add       AL,'A'       ;Add A to value
  632.         Xor       AH,AH        ;clear AH to 0
  633.         Mov       BX,[BX+2]    ;get actual string address
  634.         Mov       Byte Ptr [BX],AL      ;store AL in Drive$
  635.         Mov      Byte Ptr [BX+1],':'   ;add colon
  636.         Mov      Byte Ptr [BX+2],'\'   ;add backlash
  637.  
  638.         ADD      BX,3         ;increase address by 3 to skip "A:\"
  639.         Mov       SI,BX        ;it has to be 67 so Pathlen% value is
  640.                 Mov       DI,SI        ;calculated correctly below
  641.         Xor       DL,DL        ;clear DL to get
  642.         Mov       AH,47h       ;get current directory
  643.         Int       21h
  644.         JC        Error        ;if carry set, directory invalid
  645.         Mov       CX,64        ;find ending null in Path$
  646.         Xor       AL,AL        ;clear AL, the value to search for
  647.         Cld                    ;clear direction flag
  648.         Repnz     Scasb        ;uses ES:DI to search Path$
  649.         Mov       AX,63        ;determine length of Path$
  650.         Sub       AX,CX
  651.         Add      AX,3         ;add length of drive "A:\"
  652.         Jmp       Short finis2
  653. Error2:
  654.         Mov       AX,-1        ;return Pathlen% = -1 if error
  655. finis2:
  656.         Mov       BX,[BP+6]
  657.         Mov       [BX],AX
  658.         Pop       DI           ;restore registers used
  659.         Pop       SI
  660.         Pop       BP
  661.         Ret       4
  662. GETFULLPATH    ENDP
  663. END
  664.